﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DatabaseManagerImpl.cs" company="Marcin Jastrzebski">
//   Copyright (c) Marcin Jastrzebski (marcin@marcinj.net)
// </copyright>
// <summary>
//   The database manager implementation.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace mPassRT.Services
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Threading.Tasks;

    using Windows.Storage;
    using Windows.Storage.AccessCache;

    /// <summary>The database manager implementation.</summary>
    public class DatabaseManagerImpl : IDatabaseManager
    {
        #region Constants

        /// <summary>The database file metadata.</summary>
        private const string DatabaseFileMetadata = "Database";

        #endregion

        #region Fields

        /// <summary>The databases.</summary>
        private readonly List<Database> databases = new List<Database>();

        #endregion

        /// <summary>Initializes a new instance of the <see cref="DatabaseManagerImpl"/> class.</summary>
        public DatabaseManagerImpl()
        {
            Task task = Task.Run(async () =>
                {
                    foreach (string token in GetDatabaseTokens())
                    {
                        try
                        {
                            StorageFile file = await StorageApplicationPermissions.MostRecentlyUsedList.GetFileAsync(token);
                            this.databases.Add(new Database(token, file));
                        }
                        catch
                        {
                            // skip file that can't be added
                        }
                    }
                });
            task.Wait();
        }

        #region Public Properties

        /// <summary>Gets the current list of databases.</summary>
        /// <returns>The list of DBs.</returns>
        public IList<Database> Databases
        {
            get
            {
                return new ReadOnlyCollection<Database>(this.databases);
            }
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>Adds a database from a file.</summary>
        /// <param name="file">The file.</param>
        /// <returns>The <see cref="Database"/>.</returns>
        public Database AddDatabase(StorageFile file)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }

            // if we already have access, it's a duplicate
            if (StorageApplicationPermissions.MostRecentlyUsedList.CheckAccess(file))
            {
                throw new InvalidOperationException(string.Format("Database '{0}' has already been added.", file.Path));
            }

            string token = StorageApplicationPermissions.MostRecentlyUsedList.Add(file, DatabaseFileMetadata);
            var database = new Database(token, file);
            this.databases.Add(database);
            return database;
        }

        /// <summary>Removes the specified DB.</summary>
        /// <param name="db">The DB.</param>
        public void RemoveDatabase(Database db)
        {
            if (db == null)
            {
                throw new ArgumentNullException("db");
            }

            if (StorageApplicationPermissions.MostRecentlyUsedList.ContainsItem(db.Token))
            {
                StorageApplicationPermissions.MostRecentlyUsedList.Remove(db.Token);
            }

            this.databases.Remove(db);
        }

        #endregion

        /// <summary>Retrieves MRU file entry tokens allowing us access to previously user-selected paths.</summary>
        /// <returns>The list of tokens.</returns>
        private static IEnumerable<string> GetDatabaseTokens()
        {
            return
                StorageApplicationPermissions.MostRecentlyUsedList.Entries.Where(
                    entry => string.Equals(entry.Metadata, DatabaseFileMetadata, StringComparison.OrdinalIgnoreCase))
                                             .Select(entry => entry.Token);
        }
    }
}